package ca.etsmtl.log660.observer;

import java.util.ArrayList;

/**
 * Abstract class specifying the base behavior of an observable object
 * @author Marc
 */
public abstract class AObservable implements Cloneable {
    
	private ArrayList<IObserver> _observerList;  //Arraylist of IObserver instance
	
        /**
         * Create a new AObservable instance 
         */
        public AObservable(){
            //initialize new observer list
            _observerList = new ArrayList<IObserver>();
        }
        
	/**
	 * Add an IObserver instance to the observer list
	 * @param IObserver object observing
	 */
	public void addObserver(IObserver observer){
            //add observer to list
            _observerList.add(observer);
            _observerList.trimToSize();
            
            //push current state of AObservable to IObserver instance added
            observer.update(this.clone());
	}
	
	/**
	 * Remove specific IObserver instance
	 * @param IObserver object to remove
	 */
	public void removeObserver(IObserver observer){
		_observerList.remove(observer);
		_observerList.trimToSize();
	}
	
	/**
	 * Remove all IObserver observing
	 */
	public void purgeObservers(){
		_observerList.clear();
		_observerList.trimToSize();
	}
	
        /**
         * Start the notification of every IObserver instance observing. A cloned abstract instance is passed to each concrete IObserver instance
         */
	public void notification(INotificationAgent NotificationAgent){
            //if observable has any observer
            if(!_observerList.isEmpty()){

                //update IObserver list
                for(IObserver elements : _observerList){
                    elements.update(NotificationAgent);
                }
            }
	}     
        
        /**
         * Create a deep clone of the AObservable instance
         * @return a deep clone of the AObservable instance
         */
        protected abstract AObservable clone();
}
